/*
 * Copyright 2009 Biz-e (info@biz-e.nl)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.biz_e.gdata.data;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import nl.biz_e.gdata.util.GDataAuthentication;
import nl.biz_e.gdata.util.Utils;

import com.google.gdata.client.GoogleService;
import com.google.gdata.client.Query;
import com.google.gdata.data.BaseEntry;
import com.google.gdata.data.BaseFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

/**
 * @author Joost A. Bloemsma
 * @param <E>
 *        The type of entry (extends {@link BaseEntry}) to be returned by
 *        the service
 * @param <F>
 *        The type of Feed (extends {@link BaseFeed}) to be returned by the
 *        service
 */
public abstract class AbstractBaseManager<E extends BaseEntry<?>, F extends BaseFeed<?, E>>
		implements IItemManager<E, F> {
	private GDataAuthentication authentication;
	private GoogleService service;
	private String feedName;
	private String appName;
	private final Class<F> feedClass;
	private final Class<E> entryClass;
	
	/**
	 * Constructs a new AbstractBaseManager instance
	 * 
	 * @param authentication
	 *        Used for authentication agains the GData Service
	 * @param feedName
	 *        the name of the feed. Used to construct request URL
	 * @param feedClass
	 *        The class of F
	 * @param entryClass
	 *        the class of E
	 * @param appName
	 */
	protected AbstractBaseManager(GDataAuthentication authentication,
			String feedName, Class<F> feedClass, Class<E> entryClass,
			String appName) {
		this.appName = appName;
		this.setAuthentication(authentication);
		this.setFeedName(feedName);
		this.feedClass = feedClass;
		this.entryClass = entryClass;
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public F getFeed(Query query) throws IOException, ServiceException {
		return service.getFeed(query, this.feedClass);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<E> getAll() throws IOException, ServiceException {
		URL feedUrl;
		feedUrl = new URL(this.getBaseUrl());
		Query myQuery = new Query(feedUrl);
		myQuery.setMaxResults(Integer.MAX_VALUE);
		F feed = this.getFeed(myQuery);
		List<E> list = feed.getEntries();
		return list;
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public E getItem(String id) throws IOException, ServiceException {
		URL feedUrl;
		String url = this.getBaseUrl() + id;
		System.out.println(url);
		feedUrl = new URL(url);
		return service.getEntry(feedUrl, entryClass);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public E getEntryByUrl(String url) throws MalformedURLException,
			IOException, ServiceException {
		return service.getEntry(new URL(url), entryClass);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public E insert(E entry) throws IOException, ServiceException {
		return this.service.insert(new URL(this.getBaseUrl()), entry);
	}
	
	/**
	 * @param service
	 *        the service to set
	 * @throws AuthenticationException
	 *         if authentication failed.
	 */
	protected void setService(GoogleService service)
			throws AuthenticationException {
		this.service = service;
		this.service.setUserCredentials(this.authentication.getUserId(),
				this.authentication.getPassWord());
		// String sname = service.getServiceVersion();
		String token = service.getAuthToken(this.authentication.getUserId(),
				this.authentication.getPassWord(), null, null, "cp",
				this.appName);
		System.out.println(token);
	}
	
	/**
	 * @return the application name
	 */
	protected String getAppName() {
		return this.appName;
	}
	
	/**
	 * @return the service
	 */
	protected GoogleService getService() {
		return service;
	}
	
	/**
	 * @return the feedName
	 */
	protected String getFeedName() {
		return feedName;
	}
	
	/**
	 * @param feedName
	 *        the feedName to set
	 */
	protected void setFeedName(String feedName) {
		this.feedName = feedName;
	}
	
	/**
	 * @return The base url. Used to construct the request url
	 */
	protected String getBaseUrl() {
		String baseUrl;
		if ((feedName == null) || (authentication.getUserId() == null)) {
			baseUrl = "";
		} else {
			baseUrl = BASE_URL + feedName + "/";
			if ((Utils.DOMAIN != null) & (Utils.DOMAIN.length() > 0)) {
				baseUrl += "domain/" + Utils.DOMAIN;
			} else {
				baseUrl += authentication.getUserId();
			}
			baseUrl += "/" + getUrlExtension();
		}
		return baseUrl;
	}
	
	/**
	 * @return the authentication
	 */
	protected GDataAuthentication getAuthentication() {
		return authentication;
	}
	
	/**
	 * @param authentication
	 *        the authentication to set
	 */
	protected void setAuthentication(GDataAuthentication authentication) {
		this.authentication = authentication;
	}
	
	/**
	 * @return a feed specific url extension, like the Projection for
	 *         ContactFeed
	 */
	protected String getUrlExtension() {
		return "";
	}
}
